home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Add-On
/
Workbench Add-On - Volume 1.iso
/
Dev
/
Oberon
/
source
/
ProjectOberon
/
Reals.mod
< prev
next >
Wrap
Text File
|
1995-07-02
|
5KB
|
205 lines
(***************************************************************************
$RCSfile: Reals.mod $
Description: Low-level floating point conversions
Created by: fjc (Frank Copeland)
$Revision: 1.9 $
$Author: fjc $
$Date: 1995/06/04 23:26:41 $
Copyright © 1994, Frank Copeland.
This file is part of the Oberon-A Library.
See Oberon-A.doc for conditions of use and distribution.
Log entries are at the end of the file.
***************************************************************************)
MODULE Reals;
(*
** This module performs low-level operations on REAL and LONGREAL
** values. The values are assumed to be in IEEE floating-point format.
** At present both REAL and LONGREAL values are 32-bit single-precision
** values. In future LONGREAL will be re-implemented as 64-bit
** double-precision values.
**
** IEEE single-precision reals have the following format:
**
** SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM
** 31 23 15 7
**
** S = sign, E = exponent, M = mantissa
*)
IMPORT SYS := SYSTEM;
(*------------------------------------*)
PROCEDURE Expo* (x : REAL) : INTEGER;
(*
** This procedure extracts the exponent part of a REAL value. This is
** held in bits 23-30.
*)
BEGIN (* Expo *)
RETURN SHORT (SYS.LSH (SYS.VAL (LONGINT, x), -23)) MOD 256
END Expo;
(*------------------------------------*)
PROCEDURE ExpoL* (x : LONGREAL) : INTEGER;
BEGIN (* ExpoL *)
RETURN Expo (SHORT (x))
END ExpoL;
(*------------------------------------*)
PROCEDURE SetExpo* (e : INTEGER; VAR x : REAL);
(*
* This procedure sets the exponent part of a REAL variable. It clears bits
* 23-30 using SYS.AND() and ORs the exponent onto the cleared area.
*
* Broken down into simple expressions, the algorithm is:
* i := SYS.VAL (LONGINT, x);
* i := SYS.AND (i, 087FFFFFFH);
* e := SYS.LSH (e MOD 256, 23);
* i := SYS.LOR (i, e);
* x := SYS.VAL (REAL, i)
*)
BEGIN (* SetExpo *)
x :=
SYS.VAL
( REAL,
SYS.LOR
( SYS.AND ( SYS.VAL (LONGINT, x), 087FFFFFFH ),
SYS.LSH (LONG (e MOD 256), 23) ) )
END SetExpo;
(*------------------------------------*)
PROCEDURE SetExpoL* (e : INTEGER; VAR x : LONGREAL);
VAR y : REAL;
BEGIN (* SetExpoL *)
y := SHORT (x); SetExpo (e, y); x := LONG (y)
END SetExpoL;
(*------------------------------------*)
PROCEDURE Ten* (e : INTEGER) : REAL;
VAR result : REAL; n : INTEGER;
BEGIN (* Ten *)
result := 1.0; n := ABS (e);
WHILE n > 0 DO result := result * 10.0; DEC (n) END;
(* ^
** If you get an F-line trap at this point, and you are the proud owner
** of an Amiga 4000/040 running OS 3.1, this is *not* a compiler bug. You
** need to install a patch to fix a bug in the V40
** mathieeesingbas.library.
*)
IF e >= 0 THEN
RETURN result
ELSE
RETURN 1.0 / result
END;
END Ten;
(*------------------------------------*)
PROCEDURE TenL* (e : INTEGER) : LONGREAL;
BEGIN (* TenL *)
RETURN LONG (Ten (e))
END TenL;
(*------------------------------------*)
PROCEDURE Convert* (x : REAL; n : INTEGER; VAR d : ARRAY OF CHAR);
(*
* Converts a REAL into a string. d will contain the n most significant
* digits of x, in REVERSE order.
*)
VAR i : LONGINT;
BEGIN (* Convert *)
i := 0;
REPEAT
d [i] := CHR (ENTIER (x) MOD 10 + 30H); x := x / 10; INC (i)
UNTIL i = n;
END Convert;
(*------------------------------------*)
PROCEDURE ConvertL* (x : LONGREAL; n : INTEGER; VAR d : ARRAY OF CHAR);
BEGIN (* ConvertL *)
Convert (SHORT (x), n, d)
END ConvertL;
(*------------------------------------*)
PROCEDURE ConvertH* (x : REAL; VAR d : ARRAY OF CHAR);
(*
* Converts a REAL into a hexadecimal string.
*)
VAR i, j, k : LONGINT;
BEGIN (* ConvertH *)
d [7] := 0X; (* This should cause an index trap if d is too small. *)
(* Turn off index checking now, since we know there is enough room. *)
<*$ < IndexChk- *>
k := SYS.VAL (LONGINT, x);
i := 8;
REPEAT
DEC (i);
IF k # 0 THEN
j := k MOD 10H; k := k DIV 10H;
IF j < 10 THEN d [i] := CHR (j + 30H) ELSE d [i] := CHR (j + 37H) END
ELSE
d [i] := "0"
END;
UNTIL i = 0;
<*$ > *>
END ConvertH;
(*------------------------------------*)
PROCEDURE ConvertHL* (x : LONGREAL; VAR d : ARRAY OF CHAR);
BEGIN (* ConvertHL *)
ConvertH (SHORT (x), d)
END ConvertHL;
END Reals.
(***************************************************************************
$Log: Reals.mod $
Revision 1.9 1995/06/04 23:26:41 fjc
- Release 1.6
Revision 1.8 1995/06/04 23:24:07 fjc
- Release 1.6
Revision 1.8 1995/06/04 23:24:07 fjc
- Release 1.6
Revision 1.7 1995/05/08 17:19:37 fjc
- Added warning for the V40 mathieeesingbas SPMul/040 bug.
Revision 1.6 1995/01/26 00:48:34 fjc
- Release 1.5
Revision 1.5 1994/11/11 17:00:38 fjc
- Uses new external code interface.
Revision 1.5 1994/11/11 17:00:38 fjc
- Uses new external code interface.
Revision 1.4 1994/09/18 21:25:47 fjc
- Converted switches to pragmas/options
Revision 1.1 1994/01/15 21:39:12 fjc
- Start of revision control
***************************************************************************)